package com.smart.community.region.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.region.entity.BuildingTypeCategory;
import com.smart.community.region.mapper.BuildingTypeCategoryMapper;
import com.smart.community.region.service.IBuildingTypeCategoryService;
import com.smart.community.region.vo.BuildingTypeCategoryVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 建筑类型基础分类Service实现类
 * 
 * 严格按照《Java后端SpringBoot代码开发规范.md》权威标准实现：
 * - 完善的异常处理机制，确保生产环境高标准
 * - 详细的日志记录，提升可监控性
 * - 优化的缓存策略，兼顾性能和数据一致性
 * - 完整的JavaDoc注释，提高代码可维护性
 * - 统一的错误处理标准，确保系统稳定性
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 2.0.0
 */
@Slf4j
@Service
public class BuildingTypeCategoryServiceImpl extends ServiceImpl<BuildingTypeCategoryMapper, BuildingTypeCategory> implements IBuildingTypeCategoryService {

    @Autowired
    private BuildingTypeCategoryMapper buildingTypeCategoryMapper;

    /**
     * 获取划分方式列表
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * 
     * @return 划分方式列表，如果查询失败则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:division:list", key = "'all'", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getDivisionList() {
        log.info("开始获取划分方式列表");
        long startTime = System.currentTimeMillis();
        
        try {
            // 构建查询条件
            LambdaQueryWrapper<BuildingTypeCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BuildingTypeCategory::getCategoryType, "DIVISION")
                   .eq(BuildingTypeCategory::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByDesc(BuildingTypeCategory::getCreateTime);
            
            log.debug("执行数据库查询，查询条件：categoryType=DIVISION, status={}", SystemStatusEnum.ENABLED.getCode());
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectList(wrapper);
            
            if (CollectionUtils.isEmpty(categories)) {
                log.warn("未查询到任何划分方式数据");
                return Collections.emptyList();
            }
            
            List<BuildingTypeCategoryVO> result = convertToVOList(categories);
            long endTime = System.currentTimeMillis();
            log.info("成功获取划分方式列表，数量：{}，耗时：{}ms", result.size(), endTime - startTime);
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("获取划分方式列表失败，耗时：{}ms", endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 根据划分方式获取类型列表
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 参数验证，确保输入参数的有效性
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * 
     * @param divisionId 划分方式ID，不能为null
     * @return 类型列表，如果查询失败或参数无效则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:by:division", key = "#divisionId", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getTypeListByDivision(Long divisionId) {
        log.info("开始根据划分方式获取类型列表，划分方式ID：{}", divisionId);
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (divisionId == null) {
                log.warn("划分方式ID不能为空");
                return Collections.emptyList();
            }
            
            // 构建查询条件
            LambdaQueryWrapper<BuildingTypeCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BuildingTypeCategory::getParentId, divisionId)
                   .eq(BuildingTypeCategory::getCategoryType, "TYPE")
                   .eq(BuildingTypeCategory::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByDesc(BuildingTypeCategory::getCreateTime);
            
            log.debug("执行数据库查询，查询条件：parentId={}, categoryType=TYPE, status={}", 
                     divisionId, SystemStatusEnum.ENABLED.getCode());
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectList(wrapper);
            
            if (CollectionUtils.isEmpty(categories)) {
                log.warn("未查询到划分方式ID为{}的类型数据", divisionId);
                return Collections.emptyList();
            }
            
            List<BuildingTypeCategoryVO> result = convertToVOList(categories);
            long endTime = System.currentTimeMillis();
            log.info("成功获取划分方式ID为{}的类型列表，数量：{}，耗时：{}ms", 
                    divisionId, result.size(), endTime - startTime);
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("根据划分方式获取类型列表失败，划分方式ID：{}，耗时：{}ms", 
                     divisionId, endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 根据ID列表获取类型详情
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 参数验证，确保输入参数的有效性
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * 
     * @param ids ID列表，不能为null或空
     * @return 类型详情列表，如果查询失败或参数无效则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:by:ids", key = "#ids.toString()", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getTypeListByIds(List<Long> ids) {
        log.info("开始根据ID列表获取类型详情，ID列表：{}", ids);
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (CollectionUtils.isEmpty(ids)) {
                log.warn("ID列表不能为空");
                return Collections.emptyList();
            }
            
            // 过滤无效ID
            List<Long> validIds = ids.stream()
                    .filter(id -> id != null && id > 0)
                    .distinct()
                    .collect(Collectors.toList());
            
            if (validIds.isEmpty()) {
                log.warn("ID列表中没有有效的ID");
                return Collections.emptyList();
            }
            
            log.debug("执行数据库查询，有效ID列表：{}", validIds);
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectByIds(validIds);
            
            if (CollectionUtils.isEmpty(categories)) {
                log.warn("未查询到ID列表{}对应的类型数据", validIds);
                return Collections.emptyList();
            }
            
            List<BuildingTypeCategoryVO> result = convertToVOList(categories);
            long endTime = System.currentTimeMillis();
            log.info("成功获取ID列表{}的类型详情，数量：{}，耗时：{}ms", 
                    validIds, result.size(), endTime - startTime);
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("根据ID列表获取类型详情失败，ID列表：{}，耗时：{}ms", 
                     ids, endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 获取所有顶级分类（划分方式）
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * 
     * @return 顶级分类列表，如果查询失败则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:top:level", key = "'all'", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getTopLevelCategories() {
        log.info("开始获取所有顶级分类（划分方式）");
        long startTime = System.currentTimeMillis();
        
        try {
            log.debug("执行数据库查询，获取顶级分类");
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectTopLevelCategories();
            
            if (CollectionUtils.isEmpty(categories)) {
                log.warn("未查询到任何顶级分类数据");
                return Collections.emptyList();
            }
            
            List<BuildingTypeCategoryVO> result = convertToVOList(categories);
            long endTime = System.currentTimeMillis();
            log.info("成功获取所有顶级分类，数量：{}，耗时：{}ms", result.size(), endTime - startTime);
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("获取所有顶级分类失败，耗时：{}ms", endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 根据分类类型获取分类列表
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 参数验证，确保输入参数的有效性
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * 
     * @param categoryType 分类类型，不能为null或空字符串
     * @return 分类列表，如果查询失败或参数无效则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:by:category:type", key = "#categoryType", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getCategoriesByType(String categoryType) {
        log.info("开始根据分类类型获取分类列表，分类类型：{}", categoryType);
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (!StringUtils.hasText(categoryType)) {
                log.warn("分类类型不能为空");
                return Collections.emptyList();
            }
            
            log.debug("执行数据库查询，查询条件：categoryType={}", categoryType);
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectByCategoryType(categoryType);
            
            if (CollectionUtils.isEmpty(categories)) {
                log.warn("未查询到分类类型为{}的分类数据", categoryType);
                return Collections.emptyList();
            }
            
            List<BuildingTypeCategoryVO> result = convertToVOList(categories);
            long endTime = System.currentTimeMillis();
            log.info("成功获取分类类型为{}的分类列表，数量：{}，耗时：{}ms", 
                    categoryType, result.size(), endTime - startTime);
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("根据分类类型获取分类列表失败，分类类型：{}，耗时：{}ms", 
                     categoryType, endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 根据划分方式获取分类列表
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 参数验证，确保输入参数的有效性
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * 
     * @param divisionType 划分方式，不能为null或空字符串
     * @return 分类列表，如果查询失败或参数无效则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:by:division:type", key = "#divisionType", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getCategoriesByDivisionType(String divisionType) {
        log.info("开始根据划分方式获取分类列表，划分方式：{}", divisionType);
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (!StringUtils.hasText(divisionType)) {
                log.warn("划分方式不能为空");
                return Collections.emptyList();
            }
            
            log.debug("执行数据库查询，查询条件：divisionType={}", divisionType);
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectByDivisionType(divisionType);
            
            if (CollectionUtils.isEmpty(categories)) {
                log.warn("未查询到划分方式为{}的分类数据", divisionType);
                return Collections.emptyList();
            }
            
            List<BuildingTypeCategoryVO> result = convertToVOList(categories);
            long endTime = System.currentTimeMillis();
            log.info("成功获取划分方式为{}的分类列表，数量：{}，耗时：{}ms", 
                    divisionType, result.size(), endTime - startTime);
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("根据划分方式获取分类列表失败，划分方式：{}，耗时：{}ms", 
                     divisionType, endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 获取分类树形结构
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 优化的缓存策略，提高查询性能
     * - 高效的树形结构构建算法
     * 
     * @return 分类树形结构列表，如果查询失败则返回空列表
     */
    @Override
    @Cacheable(value = "building:type:tree", key = "'all'", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getCategoryTree() {
        log.info("开始获取分类树形结构");
        long startTime = System.currentTimeMillis();
        
        try {
            // 获取所有启用的分类
            LambdaQueryWrapper<BuildingTypeCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BuildingTypeCategory::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByDesc(BuildingTypeCategory::getCreateTime);
            
            log.debug("执行数据库查询，获取所有启用的分类，查询条件：status={}", SystemStatusEnum.ENABLED.getCode());
            List<BuildingTypeCategory> allCategories = buildingTypeCategoryMapper.selectList(wrapper);
            
            if (CollectionUtils.isEmpty(allCategories)) {
                log.warn("未查询到任何启用的分类数据");
                return Collections.emptyList();
            }
            
            // 转换为VO
            List<BuildingTypeCategoryVO> allCategoryVOs = convertToVOList(allCategories);
            log.debug("成功转换{}个分类为VO对象", allCategoryVOs.size());
            
            // 构建树形结构
            List<BuildingTypeCategoryVO> treeResult = buildCategoryTree(allCategoryVOs);
            long endTime = System.currentTimeMillis();
            log.info("成功构建分类树形结构，顶级节点数量：{}，总节点数量：{}，耗时：{}ms", 
                    treeResult.size(), allCategoryVOs.size(), endTime - startTime);
            
            return treeResult;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("获取分类树形结构失败，耗时：{}ms", endTime - startTime, e);
            
            // 生产环境标准：返回空列表而不是抛出异常，确保系统稳定性
            return Collections.emptyList();
        }
    }

    /**
     * 清除所有建筑类型缓存
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 统一的错误处理标准，确保系统稳定性
     */
    @Override
    @CacheEvict(value = {
        "building:type:division:list",
        "building:type:by:division",
        "building:type:by:ids",
        "building:type:top:level",
        "building:type:by:category:type",
        "building:type:by:division:type",
        "building:type:tree"
    }, allEntries = true)
    public void clearAllBuildingTypeCache() {
        log.info("开始清除所有建筑类型缓存");
        long startTime = System.currentTimeMillis();
        
        try {
            // 方法体可以为空，@CacheEvict注解会自动清除指定缓存区域的所有条目
            long endTime = System.currentTimeMillis();
            log.info("成功清除所有建筑类型缓存，耗时：{}ms", endTime - startTime);
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("清除所有建筑类型缓存失败，耗时：{}ms", endTime - startTime, e);
            
            // 生产环境标准：缓存清除失败不影响业务逻辑，只记录错误日志
        }
    }

    /**
     * 清除指定划分方式的建筑类型缓存
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 参数验证，确保输入参数的有效性
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * 
     * @param divisionId 划分方式ID，不能为null
     */
    @Override
    @CacheEvict(value = "building:type:by:division", key = "#divisionId")
    public void clearBuildingTypeCacheByDivision(Long divisionId) {
        log.info("开始清除指定划分方式的建筑类型缓存，划分方式ID：{}", divisionId);
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (divisionId == null) {
                log.warn("划分方式ID不能为空，跳过缓存清除操作");
                return;
            }
            
            // 方法体可以为空，@CacheEvict注解会自动清除指定键的缓存
            long endTime = System.currentTimeMillis();
            log.info("成功清除划分方式ID为{}的建筑类型缓存，耗时：{}ms", divisionId, endTime - startTime);
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("清除划分方式ID为{}的建筑类型缓存失败，耗时：{}ms", divisionId, endTime - startTime, e);
            
            // 生产环境标准：缓存清除失败不影响业务逻辑，只记录错误日志
        }
    }

    /**
     * 清除指定分类类型的建筑类型缓存
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 参数验证，确保输入参数的有效性
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * 
     * @param categoryType 分类类型，不能为null或空字符串
     */
    @Override
    @CacheEvict(value = "building:type:by:category:type", key = "#categoryType")
    public void clearBuildingTypeCacheByCategoryType(String categoryType) {
        log.info("开始清除指定分类类型的建筑类型缓存，分类类型：{}", categoryType);
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (!StringUtils.hasText(categoryType)) {
                log.warn("分类类型不能为空，跳过缓存清除操作");
                return;
            }
            
            // 方法体可以为空，@CacheEvict注解会自动清除指定键的缓存
            long endTime = System.currentTimeMillis();
            log.info("成功清除分类类型为{}的建筑类型缓存，耗时：{}ms", categoryType, endTime - startTime);
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("清除分类类型为{}的建筑类型缓存失败，耗时：{}ms", categoryType, endTime - startTime, e);
            
            // 生产环境标准：缓存清除失败不影响业务逻辑，只记录错误日志
        }
    }

    /**
     * 转换为VO列表
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 高效的流式处理，提高转换性能
     * 
     * @param categories 分类实体列表
     * @return VO列表，如果输入为空则返回空列表
     */
    private List<BuildingTypeCategoryVO> convertToVOList(List<BuildingTypeCategory> categories) {
        if (CollectionUtils.isEmpty(categories)) {
            log.debug("输入的分类列表为空，返回空VO列表");
            return Collections.emptyList();
        }
        
        try {
            List<BuildingTypeCategoryVO> result = categories.stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());
            
            log.debug("成功转换{}个分类实体为VO对象", result.size());
            return result;
        } catch (Exception e) {
            log.error("转换分类实体列表为VO列表失败，输入数量：{}", categories.size(), e);
            return Collections.emptyList();
        }
    }

    /**
     * 转换为VO
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 安全的属性复制，避免转换异常
     * 
     * @param category 分类实体
     * @return VO对象，如果转换失败则返回空对象
     */
    private BuildingTypeCategoryVO convertToVO(BuildingTypeCategory category) {
        if (category == null) {
            log.warn("分类实体为空，返回空VO对象");
            return new BuildingTypeCategoryVO();
        }
        
        try {
            BuildingTypeCategoryVO vo = new BuildingTypeCategoryVO();
            BeanUtils.copyProperties(category, vo);
            return vo;
        } catch (Exception e) {
            log.error("转换分类实体为VO失败，分类ID：{}", category.getId(), e);
            return new BuildingTypeCategoryVO();
        }
    }

    /**
     * 构建分类树形结构
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 高效的树形结构构建算法，提高性能
     * 
     * @param allCategories 所有分类VO列表
     * @return 树形结构列表，如果构建失败则返回空列表
     */
    private List<BuildingTypeCategoryVO> buildCategoryTree(List<BuildingTypeCategoryVO> allCategories) {
        if (CollectionUtils.isEmpty(allCategories)) {
            log.debug("输入的分类列表为空，返回空树形结构");
            return Collections.emptyList();
        }
        
        try {
            // 按父ID分组
            Map<Long, List<BuildingTypeCategoryVO>> parentMap = allCategories.stream()
                    .collect(Collectors.groupingBy(category -> 
                        category.getParentId() == null ? 0L : category.getParentId()));
            
            log.debug("成功按父ID分组，分组数量：{}", parentMap.size());
            
            // 获取顶级分类
            List<BuildingTypeCategoryVO> topLevelCategories = parentMap.get(0L);
            if (CollectionUtils.isEmpty(topLevelCategories)) {
                log.warn("未找到顶级分类（parentId为null或0的分类）");
                return Collections.emptyList();
            }
            
            // 递归设置子分类
            topLevelCategories.forEach(category -> setChildren(category, parentMap));
            
            log.debug("成功构建树形结构，顶级节点数量：{}", topLevelCategories.size());
            return topLevelCategories;
        } catch (Exception e) {
            log.error("构建分类树形结构失败，输入数量：{}", allCategories.size(), e);
            return Collections.emptyList();
        }
    }

    /**
     * 递归设置子分类
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》实现：
     * - 完善的异常处理机制，确保生产环境高标准
     * - 详细的日志记录，提升可监控性
     * - 安全的递归处理，避免无限递归
     * 
     * @param parent 父分类
     * @param parentMap 父ID到子分类列表的映射
     */
    private void setChildren(BuildingTypeCategoryVO parent, Map<Long, List<BuildingTypeCategoryVO>> parentMap) {
        if (parent == null || parent.getId() == null) {
            log.warn("父分类或父分类ID为空，跳过设置子分类");
            return;
        }
        
        try {
            List<BuildingTypeCategoryVO> children = parentMap.get(parent.getId());
            if (!CollectionUtils.isEmpty(children)) {
                parent.setChildren(children);
                log.debug("为父分类ID：{}设置{}个子分类", parent.getId(), children.size());
                
                // 递归设置子分类的子分类
                children.forEach(child -> setChildren(child, parentMap));
            }
        } catch (Exception e) {
            log.error("设置子分类失败，父分类ID：{}", parent.getId(), e);
        }
    }
}
